home *** CD-ROM | disk | FTP | other *** search
/ Over 1,000 Windows 95 Programs / Over 1000 Windows 95 Programs (Microforum) (Disc 1).iso / 1138 / source.zip / AREAS.C next >
C/C++ Source or Header  |  1995-02-11  |  11KB  |  461 lines

  1. /*      areas.c -- parse SOUP's AREAS file
  2.     This file is part of Paperboy, an offline mail/newsreader for Windows
  3.     Copyright (C) 1995  Michael H. Vartanian
  4.         vart@clark.net
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. /*
  24. #include <direct.h>
  25. */
  26. #include "areas.h"
  27. #include "soup.h"
  28. #include "error.h"
  29. #include "structs.h"
  30. #include "msgs.h"
  31. #include "reclaim.h"
  32.  
  33. static struct llareas * areahead=NULL;    /* Top of all data structures */
  34. char * packetpath=NULL;
  35. char * errortext;
  36.  
  37. int DLLFUNC InitSOUPDLL ()
  38. {
  39.     if (areahead!=NULL) reclaimareas(areahead);
  40.     areahead=NULL;
  41.     
  42.     return 0;
  43. }
  44.  
  45. int fgetlf (int max, FILE * stream, char * s)
  46. {
  47.     int c=0;
  48.     char * p;
  49.  
  50.     assert(stream!=NULL);
  51.     assert(s!=NULL);
  52.     assert(max>0);
  53.     
  54.  
  55. /* If feof, return NULL */
  56.     if (feof(stream)) return 0;
  57.  
  58. /* Read in characters from stream until
  59.     a) LF character reached 
  60.     b) EOF is reached
  61.     c) max-1 characters are read in
  62. */
  63.     p=s;
  64. /* TODO: Optimize this function, since it's been profiled as > 50% of our CPU time! */
  65.     while ( (c!=LFCHAR) && !(feof(stream)) && ((p-s)<(max-1)) )
  66.     {
  67.         c=getc(stream);
  68.         *p++=(char)c;
  69.     }
  70.  
  71.  
  72. /* Strip off LF, NULL terminate the string */
  73.     if (c==LFCHAR) p--;
  74.     *p='\0';    /* Null terminate the string */
  75.     return strlen(s);
  76. }
  77.  
  78.  
  79.  
  80. int savepath (const char * fname)
  81. {
  82.     char * endofpath;
  83.  
  84.     packetpath=strdup(fname);
  85.     if (packetpath==NULL) { errortext="savepath:Out of Memory"; return ERRMEM; }
  86.     endofpath=strrchr(packetpath,PATH_SEP);
  87.     if (endofpath==NULL) { errortext="savepath: Path has no slashes"; return ERRIO; }/* Path has no slashes? */
  88.     endofpath++;
  89.     *endofpath='\0';    /* NULL terminate after last slash */
  90.     return 0;    /* Everything OK */
  91. }
  92.  
  93.  
  94.  
  95. void areatype (char * encoding)
  96. {
  97. /*    m?, M? and b? become ??m (private mail)
  98.     u?, B? and i? become ??n (public news)
  99.     everything else becomes ??u (unknown)    */
  100.  
  101.     char areatype;
  102.     
  103.     if (encoding[3]=='\0')    /* If we need to figure this out */
  104.     {
  105.         switch (encoding[0])
  106.         {
  107.             case MAILTYPE:
  108.                 areatype=MAILTYPE;
  109.                 break;
  110.             case MAILMMDF:
  111.                 areatype=MAILTYPE;
  112.                 break;
  113.             case BINMAIL:
  114.                 areatype=MAILTYPE;
  115.                 break;
  116.             case RNEWSTYPE:
  117.                 areatype=NEWSTYPE;
  118.                 break;
  119.             case BINNEWS:
  120.                 areatype=NEWSTYPE;
  121.                 break;
  122.             default:
  123.                 areatype=UNKTYPE;
  124.                 break;
  125.         }
  126.         encoding[2]=areatype;
  127.     }
  128. }
  129.  
  130. static int comparearea (const void * a1, const void * a2)
  131. {
  132.     struct llareas * p1, * p2;
  133.     struct llareas ** p;
  134.     
  135.     assert(a1!=NULL);
  136.     assert(a2!=NULL);
  137.     p=(struct llareas **)a1;
  138.     p1=(struct llareas *)*p;
  139.     p=(struct llareas **)a2;
  140.     p2=(struct llareas *)*p;
  141.     assert(p1!=NULL);
  142.     assert(p2!=NULL);
  143.     assert(p1->magic==AREAMAGIC);
  144.     assert(p2->magic==AREAMAGIC);
  145.  
  146.     if (p1->isfolder && !p2->isfolder) return -1;
  147.     if (!p1->isfolder && p2->isfolder) return  1;
  148.  
  149.     return strcmp(p1->name,p2->name);
  150. }
  151.  
  152. int sortareas(void)
  153. /* Sort the areas, email first, alphabetically */
  154. {
  155.     struct llareas ** areas;
  156.     struct llareas * cur;
  157.     int p, numareas;
  158.     unsigned int arraysize;
  159.  
  160.     /* We create an array large enough to hold all the areas */
  161.     arraysize=sizeof(struct llareas)*GetNumAreas();
  162.     areas=(struct llareas **)malloc(arraysize);
  163.     if (areas==NULL) { errortext="sortareas: qsortarray"; return ERRMEM; }
  164.     memset(areas,0,sizeof(arraysize));
  165.  
  166.     /* Stuff pointers into the array */
  167.     cur=areahead;
  168.     numareas=GetNumAreas();
  169.     for (p=0; p<numareas; p++)
  170.     {
  171.         assert(cur!=NULL);
  172.         assert(cur->magic==AREAMAGIC);
  173.         areas[p]=cur;
  174.         cur=cur->next;
  175.     }
  176.  
  177.     /* Sort the array */
  178.     qsort(areas, numareas, sizeof(struct llareas *), comparearea);
  179.  
  180.     /* Reassmeble the linked list */
  181.     areahead=areas[0];
  182.     for (p=0; p<numareas-1; p++)
  183.         areas[p]->next=areas[p+1];
  184.  
  185.     areas[p]->next=NULL;    /* End of list */
  186.  
  187.     free(areas);
  188.     return 0;
  189. }
  190.  
  191. int DLLFUNC LoadAreas (const char * areasfname)
  192. {
  193.     int result;
  194.     int holderror;
  195.     struct llareas * cur;
  196.     
  197.     holderror=0;
  198.  
  199. /* Save path for future use */
  200.     result=savepath(areasfname);
  201.     if (result) holderror=result;
  202.  
  203. /* Read through AREAS file, recording all pertinent information */
  204.     result=parseareas (areasfname);
  205.     if (result) holderror=result;
  206.     
  207. /* Figure out the message type from the encoding */
  208.     cur=areahead;
  209.     while (cur!=NULL)
  210.     {
  211.         areatype(cur->encoding);
  212.         cur=cur->next;
  213.     }
  214.  
  215. /* Sort areas */
  216.     result=sortareas();
  217.     if (result) holderror=result;
  218.  
  219. /* Load in message summaries from whatever index (or not) we can use */
  220.     cur=areahead;
  221.     while (cur!=NULL)
  222.     {
  223.         result=parsemsg (cur);
  224.         if (result) holderror=result;
  225.         cur=cur->next;
  226.     }
  227.     return holderror;
  228. }
  229.  
  230. void DLLFUNC RemoveArea (char * foldername)
  231. {
  232.     struct llareas * cur, * prev;
  233.  
  234.     assert(foldername!=NULL);
  235.     
  236.     /* See if a folder with that name already exists, delete if so */
  237.     /* Case 0,1 */
  238.     while ( areahead && (strcmp(areahead->name,foldername)==0) )
  239.     {
  240.         /* Remove from head of list */
  241.         cur=areahead;
  242.         areahead=areahead->next;
  243.         reclaimgroup(cur);
  244.         free(cur);
  245.     }
  246.  
  247.     /* Case 2,3 */
  248.     prev=areahead;
  249.     while (prev!=NULL && prev->next!=NULL)
  250.     {
  251.         if (strcmp(prev->next->name,foldername)==0)
  252.         {
  253.             /* Remove from middle of list */
  254.             cur=prev->next;
  255.             prev->next=cur->next;
  256.             reclaimgroup(cur);
  257.             free(cur);
  258.         }
  259.         else prev=prev->next;
  260.     }
  261. }
  262.  
  263. int DLLFUNC LoadFolder (char * foldername, char * folderfile, char * folderdesc)
  264. {
  265.     struct llareas * cur;
  266.     int holderror,result;
  267.  
  268.     holderror=0;
  269.  
  270.     assert(foldername!=NULL);
  271.     assert(folderfile!=NULL);
  272.     assert(folderdesc!=NULL);
  273.  
  274.     /* Delete if we've already used it */
  275.     RemoveArea(foldername);
  276.     
  277.     /* Create new folder */
  278.     cur=(struct llareas *) malloc(sizeof(struct llareas));
  279.     if (cur==NULL) { errortext="LoadFolder: new folder"; return ERRMEM; }
  280.     memset(cur,0,sizeof(struct llareas)); /* Zero it out */
  281.     cur->magic=AREAMAGIC;
  282.     cur->isfolder=1;
  283.  
  284.     /* Add new folder to top of arealist */
  285.     cur->next=areahead;
  286.     areahead=cur;
  287.     
  288.     /* Add data to folder */
  289.     cur->head=NULL;    /* No messages yet */
  290.     cur->name=strdup(foldername);
  291.     if (cur->name==NULL) { errortext="LoadFolder:foldername"; return ERRMEM; }
  292.     cur->prefix=strdup(folderfile);
  293.     if (cur->prefix==NULL) { errortext="LoadFolder:folderfile"; return ERRMEM; }
  294.     cur->desc=strdup(folderdesc);
  295.     if (cur->desc==NULL) { errortext="LoadFolder:folderdesc"; return ERRMEM; }
  296.     strcpy(cur->encoding,"bnm");    /* Binary mail, no index, private mail */ 
  297.  
  298.     /* Sort areas */
  299.     result=sortareas();
  300.     if (result) holderror=result;
  301.  
  302.     result=parsemsg(cur);    /* Read in messages */
  303.     if (result) holderror=result;
  304.  
  305.     return (holderror);
  306. }
  307.  
  308. int parseareas (const char * areasfname)
  309. {
  310.     FILE * fareas;
  311.     char * prefix, * name, * encode, * desc;
  312.     struct llareas * cur;
  313.     char line[MAXLINE];
  314.     char newprefix[MAXLINE];
  315.  
  316. /* Check for existence of file, return error if doesn't exist */
  317.     if (areasfname==NULL) { errortext="parseareas: areasfname NULL"; return ERRIO;}
  318.     fareas=fopen(areasfname,"rb");    /* MS-DOS C compilers like binary */
  319.     if (fareas==NULL) { errortext="parseareas: areasfname not found"; return ERRIO; }
  320.  
  321. /* Until EOF, read in each line of AREAS file, adding to top of linked list 
  322.         Check for EOF
  323.         Get next line, terminated by LF
  324.         Extract prefix, Extract area name, Extract encoding, 
  325.         Extract description, if exists
  326.         Add to end of linked list 
  327.  */
  328.  
  329.     while (!feof(fareas))
  330.     {
  331.         fgetlf(sizeof(line)-1,fareas,line);
  332.         prefix=strtok(line,SOUPSEP);
  333.         name=strtok(NULL,SOUPSEP);
  334.         encode=strtok(NULL,SOUPSEP);
  335.         desc=strtok(NULL,SOUPSEP);        /* NULL if not present */
  336.         /* Remaining fields we ignore */
  337.  
  338.         /* If we don't get all valid fields, we skip this record */
  339.         if ( !prefix || !(*prefix) ) continue;
  340.         if ( !name   || !(*name  ) ) continue;
  341.         if ( !encode || !(*encode) ) continue;
  342.         if (strlen(encode)<2) continue;    /* Need two valid characters */
  343.  
  344.         /* Allocate and add to head of linked list */
  345.         cur=(struct llareas    *)malloc(sizeof(struct llareas));
  346.         if (cur==NULL) { errortext="parseareas: head linked list"; return ERRMEM;}
  347.         memset(cur,0,sizeof(struct llareas));    /* Zero it out */
  348.         cur->magic=AREAMAGIC;
  349.         cur->next=areahead;
  350.         areahead=cur;
  351.  
  352.         /* Put data into linked-list structure */
  353.         cur->head=NULL;     /* No messages yet */
  354.         /* Create a fully qualified pathname for prefix */
  355.         assert(packetpath!=NULL);
  356.         strcpy(newprefix,packetpath);
  357.         strcat(newprefix,prefix);
  358.         strcat(newprefix,MSGEXT);
  359.         cur->prefix=strdup(newprefix);
  360.         if (cur->prefix==NULL) { errortext="parseareas: prefix"; return ERRMEM; }
  361.         cur->name=strdup(name);
  362.         if (cur->name==NULL) { errortext="parseareas: name"; return ERRMEM; }
  363.         if (desc!=NULL)
  364.         {
  365.             cur->desc=strdup(desc);
  366.             if (cur->desc==NULL) { errortext="parseareas: desc"; return ERRMEM; }
  367.         } else cur->desc=strdup("");    /* No description available */
  368.         strncpy(cur->encoding,encode,sizeof(cur->encoding)-1);
  369.     }
  370.  
  371.     fclose(fareas);
  372.     return 0;
  373. }
  374.  
  375.  
  376.  
  377. int DLLFUNC GetNumAreas (void)
  378. {
  379. /* Count number of nodes in linked list */
  380.     struct llareas * cur;
  381.     unsigned int count=0;
  382.  
  383.     cur=areahead;
  384.  
  385.     while (cur!=NULL)
  386.     {
  387.         cur=cur->next;
  388.         count++;
  389.     }
  390.  
  391.     return count;
  392. }
  393.  
  394. struct llareas * findarea (int index)
  395. /* Goes to [index] entry in linked list */
  396. {
  397.     struct llareas * cur;
  398.     int max;
  399.     int count=1;
  400.  
  401.     assert(index>0);
  402.     max=GetNumAreas();
  403.     assert(index<=max);
  404.  
  405.     cur=areahead;
  406.  
  407.     while (cur!=NULL && count!=index)
  408.     {
  409.         cur=cur->next;
  410.         count++;
  411.     }
  412.  
  413.     assert(cur!=NULL);
  414.  
  415.     return cur;
  416. }
  417.  
  418.  
  419. int DLLFUNC IsFolder (int index)
  420. {
  421.     struct llareas * cur;
  422.     cur=findarea(index);
  423.     return cur->isfolder;
  424. }
  425.  
  426. char * DLLFUNC GetAreaName (int index)
  427. {
  428.     struct llareas * cur;
  429. /* Find node matching index */
  430.     cur=findarea(index);
  431.     return cur->name;
  432. }
  433.  
  434.  
  435.  
  436. char * DLLFUNC GetAreaEncoding (int index)
  437. {
  438.     struct llareas * cur;
  439. /* Find node matching index */
  440.     cur=findarea(index);
  441.     return cur->encoding;
  442. }
  443.  
  444.  
  445.  
  446. char * DLLFUNC GetAreaDesc (int index)
  447. {
  448.     struct llareas * cur;
  449. /* Find node matching index */
  450.     cur=findarea(index);
  451.     if (cur->desc) return cur->desc;
  452.     return "";
  453. }
  454.  
  455. char * DLLFUNC GetErrorText (void)
  456. {
  457.     if (errortext!=NULL) return errortext;
  458.     else return "No Error";
  459. }
  460.  
  461.